package com.a01_2021.thousandstimes.general.jwt.service;

import com.a01_2021.thousandstimes.exception.CustomException;
import com.a01_2021.thousandstimes.exception.CustomExceptionType;
import com.a01_2021.thousandstimes.general.entity.SysUser;
import com.a01_2021.thousandstimes.general.jwt.JwtTokenUtil;
import com.a01_2021.thousandstimes.general.mapper.SysUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author E1xP@foxmail.com
 * @Version 1.0
 * @PACKAGE_NAME com.a01_2021.thousandstimes.auth.jwt
 * @CLASS_NAME JwtAuthService
 * @Description TODO Jwt令牌Service
 * @Date 2021/2/23 下午 9:32
 **/
@Service
public class JwtAuthService {

    @Resource
    UserDetailsService userDetailsService;
    @Resource
    JwtTokenUtil jwtTokenUtil;
    @Resource
    AuthenticationManager authenticationManager;

    @Resource
    SysUserMapper sysUserMapper;

    /**
     * 登录获得JWT令牌
     *
     * @param username   用户名
     * @param password   密码
     * @param instanceId 所属实例id
     * @return 返还Jwt令牌
     * @throws CustomException 当登录失败时抛出自定义异常（登陆失败
     */
    public String login(String username, String password, String instanceId) throws CustomException {
        try {
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
            Authentication authentication = authenticationManager.authenticate(token);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (AuthenticationException e) {//若认证失败会抛出异常
            throw new CustomException(CustomExceptionType.USER_INPUT_ERROR, "用户名或密码不正确");
        }
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);

        //获取用户id
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        SysUser sysUser = sysUserMapper.selectOne(queryWrapper);

        return jwtTokenUtil.generateToken(userDetails, instanceId, sysUser.getId());
    }

    /**
     * 通过旧令牌刷新令牌
     *
     * @param oldToken 旧令牌
     * @return 若令牌未过期返还新令牌，若过期返还NULL
     */
    public String refreshToken(String oldToken) {
        if (!jwtTokenUtil.isTokenExpired(oldToken)) {
            //若未过期返还刷新后的token
            return jwtTokenUtil.refreshToken(oldToken);
        }
        //过期则返还null
        return null;
    }
}
